home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / terms / kermit / b / ckvker.mms < prev    next >
Encoding:
Text File  |  1993-06-30  |  16.7 KB  |  427 lines

  1. ! CKVKER.MMS, 15-Oct-1992
  2. !
  3. ! -- MMS description file for building C-Kermit 5 on VAX/VMS 5.x systems --
  4. !
  5. ! Author: Piet W. Plomp, ICCE, Groningen University, The Netherlands,
  6. ! Internet: piet@icce.rug.nl, piet@asterix.icce.rug.nl.
  7. ! Parts adapted from both ckvker.mak by Terry Kennedy and others, and
  8. ! ckvker.com by Lee Tibbert and others.
  9. !
  10. ! Copyright (C) 1985, 1992, Trustees of Columbia University in the City of
  11. ! New York.  Permission is granted to any individual or institution to use
  12. ! this software as long as it is not sold for profit.  This copyright
  13. ! notice must be retained.  This software may not be included in commercial
  14. ! products without written permission of Columbia University.
  15. !
  16. ! INSTALLATION NOTES:
  17. !
  18. ! Before proceeding, read the instructions below, and also read the file
  19. ! ckvker.bwr (the "beware file").
  20. ! - Make sure you have at least 5000 blocks file space available (this
  21. !   includes space for the sources).
  22. ! - Make sure you have all required sources (ckc*.c, cku*.c, ckv*.c plus
  23. !   corresponding ck*.h files as well as ckwart.c and ckcpro.w) in the
  24. !   current directory.
  25. ! - Rename this file to "DESCRIP.MMS" and put it in the current directory.
  26. ! - If you want SHARED LIBRARY SUPPORT (please read NOTES below),
  27. !   you must set a global symbol WERMIT_SHARE having any non-empty
  28. !   string value (e.g. enter
  29. !       WERMIT_SHARE :== "T"
  30. !   at the VMS command line prompt before starting MMS).
  31. !   If you change your mind and don't want shared library support after all,
  32. !   you may delete the symbol by entering
  33. !       DEL/SYM/GLO WERMIT_SHARE
  34. !   at the VMS prompt.
  35. ! - This description file will automatically detect the presence of
  36. !   TCP/IP networking products on your system, and builds one of them into
  37. !   C-Kermit.
  38. !   The following products are recognized (in decreasing order of priority):
  39. !       TGV MultiNet TCP/IP,
  40. !       Wollongong WIN TCP,
  41. !       DEC TCP/IP (UCX) support.
  42. !   You may override the automatic detection by setting a global symbol
  43. !   net_option, having one of the following string values:
  44. !       NET_OPTION :== "NONET"      forces omission of network support
  45. !       NET_OPTION :== "MULTINET"   build with TGV MultiNet
  46. !       NET_OPTION :== "WINTCP"     build with Wollongong WIN/TCP
  47. !       NET_OPTION :== "DEC_TCPIP"  build with DEC TCP/IP
  48. !
  49. !   The net_option symbol can be deleted by typing
  50. !       DEL/SYM/GLO NET_OPTION
  51. !   at the VMS prompt.
  52. !
  53. ! - You may tailor the defines for the C compiler to meet your own
  54. !   requirements.  Look at the description before CCDEFS section below
  55. ! - Issue:                      to build:
  56. !       MMS                     WERMIT.EXE
  57. !       MMS WERMIT              WERMIT.EXE
  58. !       MMS CKVCVT              CKVCVT.EXE
  59. !       MMS ALL                 both WERMIT.EXE and CKVCVT.EXE
  60. ! - set a symbol to the executable as follows:
  61. !       WERMIT :== $your$disk:[your.full.path]WERMIT.EXE
  62. !   DON'T FORGET THE FIRST '$'.
  63. !   Now you can give wermit command-line arguments.
  64. !
  65. ! After WERMIT or CKVCVT was built successfully you can run "MMS CLEANUP"
  66. ! to remove all .obj files, ckcpro.c and wart.exe.
  67. !
  68. ! This description file was developed and tested on a VAX 8650 running
  69. ! VAX/VMS 5.4, using MMS version 2.5 (type MMS/IDENT to show
  70. ! the version and find out if MMS is installed on your VMS system).
  71. ! The C-compiler had version 3.2.
  72. !
  73. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  74. !
  75. !   NOTES:
  76. !
  77. !   Refer to ckvins.doc for an overview of ways to build C-Kermit for VMS.
  78. !   Building C-Kermit for VMS using this file and MMS is just a handy
  79. !   alternative.
  80. !   It is not meant to be the standard way to build C-Kermit for VMS.
  81. !   However, currently only this file offers shared library support.
  82. !
  83. !   C-Kermit can also be built for many other systems.
  84. !   Refer to ck?ker.mak for details.
  85. !
  86. !   This file does not contain support for VMS versions below 5.0 and
  87. !   VAX C versions below 3.0.
  88. !
  89. !   WARNING: older VMS SHARED LIBRARIES are 'buggy': they may contain
  90. !   undocumented public variables that may interfere with kermit's
  91. !   own variables. Only the newer ones, that is from VMS version 5.2
  92. !   are reported to be reliable.
  93. !
  94. !   If you use shared library support, this description file uses
  95. !   a temporary file name "WERSHARE.OPT" as a linker options file
  96. !   (this cannot be done through sys$input:, because that is grabbed by MMS).
  97. !   After completion all versions of this file will be removed.
  98. !
  99. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  100. !
  101. ! Initialization Section:
  102. ! Note: wermit, ckvcvt and all have their own *_first and *_last sections
  103. ! (see Dependencies section). There is no .LAST in this file
  104. !
  105. .FIRST
  106.     @ ! echo: write to stdout; tab: some spacing
  107.     @ echo = "write sys$output"
  108.     @ tab = "    "
  109.     @ warning = "WARNING: "
  110.     @ fatal = "FATAL ERROR: "
  111.  
  112. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  113. !
  114. ! Macro Section:
  115. !
  116. ! CC: use default macro
  117. !
  118. ! CCDEFS -
  119. ! Some site options you might want to add:
  120. !  NOPUSH    - Disallow access to DCL from within Kermit.
  121. !  NODEBUG   - Remove all debugging code to make C-Kermit smaller and faster.
  122. !
  123. ! The following site options are used in this file as distributed:
  124. !  DYNAMIC   - Allocate packet and other buffers dynamically.
  125. !  NOJC      - Omit Job-Control related code.
  126. !  NOSETBUF  - Don't make console i/o unbuffered.
  127. !  CK_CURSES - Include fullscreen file transfer display.
  128. !  KANJI     - Include Kanji file transfer translation.
  129. !  IFDEBUG   - Avoid calls to debug() if debugging not on: faster execution
  130. !              but bigger .EXE file.  If you don't need debugging, replace
  131. !              this by NODEBUG.
  132. CCDEFS = -
  133.     /DEFINE=("DYNAMIC", "NOJC", "NOSETBUF", "CK_CURSES", "KANJI", -
  134.             "IFDEBUG", -
  135.             'net_option,'cc_ver,'vms_ver,'share_opt)
  136.  
  137. CCFLAGS = -
  138.     /NOLIST/OBJECT=$(MMS$TARGET) /DEBUG=TRACE/OPTIMIZE $(CCDEFS) -
  139.     $(MMS$SOURCE)
  140.  
  141. SHAREOPTS = WERSHARE/OPTION
  142.  
  143. OBJECT_MODULES = ckcmai.obj, -
  144.     ckcfns.obj, ckcfn2.obj, ckcfn3.obj, ckcnet.obj, ckcpro.obj, -
  145.     ckuusr.obj, ckuus2.obj, ckuus3.obj, ckuus4.obj, ckuus5.obj, -
  146.     ckuus6.obj, ckuus7.obj, ckuusx.obj, ckuusy.obj, -
  147.     ckucmd.obj, ckudia.obj, ckuscr.obj, ckuxla.obj, -
  148.     ckvcon.obj, ckvioc.obj, ckvfio.obj, ckvtio.obj
  149.  
  150. LIBWINTCP   = twg$common:[netdist.lib]twglib.olb/library
  151. LIBDECTCPIP = sys$library:ucx$ipc.olb/library
  152.  
  153. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  154. !
  155. ! Rule Section:
  156. !
  157. .C.OBJ
  158.     @ echo tab + "Compiling $(MMS$SOURCE)"
  159.     @ $(CC) $(CCFLAGS)
  160.  
  161. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  162. !
  163. ! Dependencies Section:
  164. !
  165. wermit : ckvker_first wermit_first wermit.exe  ckvker_last wermit_last
  166.     @ continue
  167.  
  168. ckvcvt : ckvker_first ckvcvt_first ckvcvt.exe  ckvker_last ckvcvt_last
  169.     @ continue
  170.  
  171. all : ckvker_first wermit_first wermit.exe ckvcvt_first ckvcvt.exe -
  172.     ckvker_last all_last
  173.     @ continue
  174.  
  175. wermit.exe : $(OBJECT_MODULES)
  176.     @ echo tab + "Linking $(MMS$TARGET_NAME)", -
  177.         share_text, ", ", net_name, " network support"
  178.  
  179.     @ if net_option .eqs. "NONET" .and. share_opt .eqs. "NOVMSSHARE" then -
  180.         $(LINK) $(LINKFLAGS) -
  181.         $(OBJECT_MODULES) ! assume lnk$library set
  182.     @ if net_option .eqs. "NONET" .and. share_opt .eqs. "VMSSHARE" then -
  183.         $(LINK) $(LINKFLAGS) -
  184.         $(OBJECT_MODULES), $(SHAREOPTS)
  185.  
  186.     @ if net_option .eqs. "MULTINET" then -     ! always use options file
  187.         $(LINK) $(LINKFLAGS) -
  188.         $(OBJECT_MODULES), $(SHAREOPTS)
  189.  
  190.     @ if net_option .eqs. "WINTCP" .and. share_opt .eqs. "NOVMSSHARE" then -
  191.         $(LINK) $(LINKFLAGS) $(OBJECT_MODULES), -
  192.         $(LIBWINTCP)        ! assume lnk$library set
  193.     @ if net_option .eqs. "WINTCP" .and. share_opt .eqs. "VMSSHARE" then -
  194.         $(LINK) $(LINKFLAGS) $(OBJECT_MODULES), $(SHAREOPTS), -
  195.         $(LIBWINTCP)
  196.  
  197.     @ if net_option .eqs. "DEC_TCPIP" .and. share_opt .eqs. "NOVMSSHARE" then -
  198.         $(LINK) $(LINKFLAGS) $(OBJECT_MODULES), -
  199.         $(LIBDECTCPIP)      ! assume lnk$library set
  200.     @ if net_option .eqs. "DEC_TCPIP" .and. share_opt .eqs. "VMSSHARE" then -
  201.         $(LINK) $(LINKFLAGS) $(OBJECT_MODULES), $(SHAREOPTS), -
  202.         $(LIBDECTCPIP)
  203.     @ ! Just speculating (pwp 92-10-15); to test comment previous if, then
  204.     @ ! uncomment next 2 lines and companion section in link section
  205.     @ ! if net_option .eqs. "DEC_TCPIP" .and. share_opt .eqs. "VMSSHARE" then -
  206.       !  $(LINK) $(LINKFLAGS) $(OBJECT_MODULES), $(SHAREOPTS)
  207.  
  208. ckvcvt.exe : ckvcvt.obj
  209.     @ echo tab + "Linking $(MMS$TARGET_NAME)"
  210.     @ if share_opt .eqs. "NOVMSSHARE" then -
  211.         link /exec=ckvcvt.exe ckvcvt.obj    ! assume lnk$library logical set
  212.     @ if share_opt .eqs. "VMSSHARE" then -
  213.         $(LINK) $(LINKFLAGS) ckvcvt.obj,$(SHAREOPTS)
  214.  
  215. ckvioc.obj : ckvioc.c ckvioc.h ckcdeb.h
  216.  
  217. ckvfio.obj : ckvfio.c ckcdeb.h ckcfil.h ckuver.h
  218.  
  219. ckvtio.obj : ckvtio.c ckcdeb.h ckcnet.h ckuver.h
  220.  
  221. ckvcon.obj : ckvcon.c ckcker.h ckcdeb.h ckcasc.h ckcnet.h
  222.  
  223. ckwart.obj : ckwart.c
  224.  
  225. wart.exe : ckwart.obj
  226.     @ echo tab + "Linking $(MMS$TARGET_NAME)"
  227.     @ if share_opt .eqs. "NOVMSSHARE" then -
  228.         link /exec=wart.exe ckwart.obj      ! assume lnk$library logical set
  229.     @ if share_opt .eqs. "VMSSHARE" then -
  230.         $(LINK) $(LINKFLAGS) ckwart.obj,$(SHAREOPTS)
  231.  
  232. ckcpro.obj : ckcpro.c ckcker.h ckcdeb.h ckcasc.h
  233.  
  234. ckcpro.c : ckcpro.w wart.exe ckcdeb.h ckcasc.h ckcker.h
  235.     @ echo "WART $(MMS$SOURCE) CKCPRO.C"
  236.     @ wart = "$" + f$parse("WART.EXE",,,"DEVICE") + -
  237.         f$parse("WART.EXE",,,"DIRECTORY") + "WART"
  238.     @ wart ckcpro.w ckcpro.c
  239.  
  240. ckcmai.obj : ckcmai.c ckcker.h ckcdeb.h ckcsym.h ckcasc.h ckcnet.h ckcfil.h
  241.  
  242. ckcnet.obj : ckcnet.c ckcker.h ckcdeb.h ckcnet.h
  243.  
  244. ckcfns.obj : ckcfns.c ckcker.h ckcdeb.h ckcsym.h ckcasc.h ckcfil.h
  245.  
  246. ckcfn2.obj : ckcfn2.c ckcker.h ckcdeb.h ckcsym.h ckcasc.h
  247.  
  248. ckcfn3.obj : ckcfn3.c ckcker.h ckcdeb.h ckcsym.h ckcasc.h ckcfil.h
  249.  
  250. ckuxla.obj : ckuxla.c ckcker.h ckcdeb.h ckcxla.h ckuxla.h
  251.  
  252. ckuusr.obj : ckuusr.c -
  253.              ckucmd.h ckcker.h ckuusr.h ckcdeb.h ckcxla.h ckuxla.h -
  254.              ckcasc.h ckcnet.h
  255.  
  256. ckuus2.obj : ckuus2.c -
  257.              ckucmd.h ckcker.h ckuusr.h ckcdeb.h ckcxla.h ckuxla.h ckcasc.h
  258.  
  259. ckuus3.obj : ckuus3.c -
  260.              ckucmd.h ckcker.h ckuusr.h ckcdeb.h ckcxla.h ckuxla.h -
  261.              ckcasc.h ckcnet.h ckcfil.h
  262.  
  263. ckuus4.obj : ckuus4.c -
  264.              ckucmd.h ckcker.h ckuusr.h ckcdeb.h ckcxla.h ckuxla.h -
  265.              ckcasc.h ckcnet.h
  266.  
  267. ckuus5.obj : ckuus5.c -
  268.              ckucmd.h ckcker.h ckuusr.h ckcdeb.h ckcxla.h ckuxla.h ckcasc.h
  269.  
  270. ckuus6.obj : ckuus6.c -
  271.              ckucmd.h ckcker.h ckuusr.h ckcdeb.h ckcasc.h
  272.  
  273. ckuus7.obj : ckuus7.c -
  274.              ckucmd.h ckcker.h ckuusr.h ckcdeb.h ckcxla.h ckuxla.h -
  275.              ckcasc.h ckcnet.h
  276.  
  277. ckuusx.obj : ckuusx.c  ckcker.h ckuusr.h ckcdeb.h ckcasc.h
  278.  
  279. ckuusy.obj : ckuusy.c  ckcker.h ckcfil.h ckcdeb.h ckcasc.h
  280.  
  281. ckucmd.obj : ckucmd.c ckcasc.h ckucmd.h ckcdeb.h
  282.  
  283. ckudia.obj : ckudia.c ckcker.h ckcdeb.h ckucmd.h ckcasc.h
  284.  
  285. ckuscr.obj : ckuscr.c ckcker.h ckcdeb.h ckcasc.h
  286.  
  287. ckvker_first :
  288.     @ ! check for the C runtime-library
  289.     @ ! variable share_opt can get three values: "" (error),
  290.     @ ! VMSSHARE (shareable lib found), or NOVMSSHARE (Normal lib)
  291.     @ share_opt = ""            ! preset to error (no runtime lib)
  292.     @ if "''wermit_share'" .and. -
  293.         f$search("sys$share:vaxcrtl.exe") .nes. "" then -
  294.         share_opt = "VMSSHARE"  ! Shared library support wanted and possible
  295.     @ if share_opt .eqs. "" .and. -
  296.         f$search("sys$library:vaxcrtl.olb") .nes. "" -
  297.         then share_opt = "NOVMSSHARE"! Normal non-shareable library
  298.     @ if share_opt .eqs. "NOVMSSHARE" then -
  299.         define lnk$library sys$library:vaxcrtl.olb
  300.  
  301.     @ ! abort if neither shareable nor non-shareable run time lib found
  302.     @ if share_opt .eqs. "" then echo tab + fatal + "No run time library."
  303.     @ if share_opt .eqs. "" then exit
  304.  
  305.     @ ! save pending net_option (may be "") into net_override
  306.     @ net_override = "''net_option'"
  307.  
  308.     @ ! detect and decide on network support -- start with lowest priority
  309.     @ if f$search("sys$library:ucx$ipc.olb") .nes. "" then -
  310.             net_option = "DEC_TCPIP"
  311.     @ ! next but lowest priority -- may overwrite previous
  312.     @ if f$search("TWG$COMMON:[NETDIST.LIB]TWGLIB.OLB") .nes. "" then -
  313.             net_option = "WINTCP"
  314.     @ ! highest priority -- may overwrit previous
  315.     @ if f$search("multinet:multinet_socket_library.exe") .nes. "" then -
  316.         net_option = "MULTINET"
  317.     @ ! check for override (override automatic detection)
  318.     @ if net_override .nes. "" then net_option = net_override
  319.     @ ! if net_option still not set, disable net support
  320.     @ if "''net_option'" .eqs. "" then net_option = "NONET"
  321.  
  322.     @ ! net_option set, now set net_name, describing the product
  323.     @ if "''net_option'" .eqs. "NONET" then net_name = "no"
  324.     @ if net_option .eqs. "MULTINET" then net_name = "TGV MultiNet TCP/IP"
  325.     @ if net_option .eqs. "WINTCP" then net_name = "Wollongong WIN/TCP"
  326.     @ if net_option .eqs. "DEC_TCPIP" then net_name = "DEC TCP/IP"
  327.  
  328.     @ ! if override contained an error, then net_name will not be set
  329.     @ if "''net_name'" .eqs. "" then -
  330.         echo tab + fatal , "Invalid net_option ", net_override
  331.     @ if "''net_name'" .eqs. "" then exit
  332.  
  333.     @ ! define some logicals for WINTCP
  334.     @ if net_option .eqs. "WINTCP" then -
  335.         define /nolog vaxc$include twg$tcp:[netdist.include],sys$library
  336.     @ if net_option .eqs. "WINTCP" then -
  337.         define /nolog sys twg$tcp:[netdist.include.sys]
  338.  
  339.     @ ! set linker options file
  340.     @ wershare_file = "wershare.opt"
  341.  
  342.     @ ! set text for banner, default empty string
  343.     @ share_text = ""
  344.     @ if share_opt .eqs. "VMSSHARE" then share_text = ", shared library"
  345.  
  346.     @ ! open options file, if appropriate
  347.     @ if share_opt .eqs. "VMSSHARE" .or. net_option .eqs. "MULTINET" then -
  348.         open/write wermit_opt_file 'wershare_file'  ! fail handled by MMS
  349.     @ if share_opt .eqs. "VMSSHARE" then -
  350.         write wermit_opt_file "sys$share:vaxcrtl.exe/share"
  351.     @ if net_option .eqs. "MULTINET" then -
  352.         write wermit_opt_file "multinet:multinet_socket_library.exe/share"
  353.     @ ! Just speculating (pwp 92-10-15);
  354.     @ ! to test uncomment this and companion section in link section
  355.     @ ! if net_option .eqs. "DEC_TCPIP" then -
  356.       !  write wermit_opt_file "sys$share:ucx$ipc.exe/share"
  357.     @ if share_opt .eqs. "VMSSHARE" .or. net_option .eqs. "MULTINET" then -
  358.         close wermit_opt_file
  359.     @ ! no need to add WINTCP information to options file
  360.     @ ! options for shared linking written to options file
  361.  
  362.     @ ! detect and decide on operating system version
  363.     @ _osversion = f$edit(f$getsyi("version"),"compress")
  364.     @ os_fieldtest = "F"
  365.     @ if f$extract(0,1,_osversion) .nes. "V" then os_fieldtest = "T"
  366.     @ if os_fieldtest .eqs. "T" then echo warning + -
  367.         "You appear to be running a Field Test version of VMS."
  368.     @ if os_fieldtest .eqs. "T" then echo tab + -
  369.         "This description file will assume that the operating system"
  370.     @ if os_fieldtest .eqs. "T" then echo tab + -
  371.         "version is at least v5.0."
  372.     @ if os_fieldtest .eqs. "T" then echo ""
  373.     @ if os_fieldtest .eqs. "T" then _osversion = "V5.0"
  374.     @ del/sym os_fieldtest
  375.     @ ! end of if os_fieldtest checks
  376.     @ _osmajor = 0+f$extract(1,1,_osversion)
  377.     @ _osminor = 0+f$extract(3,1,_osversion)
  378.     @ vms_ver = "VMS_V" + f$string(_osmajor) + f$string(_osminor)
  379.  
  380.     @ ! detect and decide on C compiler version
  381.     @ cc_ver = "VAXC030"
  382.     @ if f$search("sys$library:xabrudef.h") .nes. "" then cc_ver = "VAXC031"
  383.     @ old_compiler = "F"
  384.     @ if cc_ver .nes. "VAXC031" then old_compiler = "T"
  385.     @ if old_compiler .eqs. "T" then echo warning + -
  386.         "Your system has an older version of the VAX C compiler."
  387.     @ if old_compiler .eqs. "T" then echo tab + -
  388.         "VMS C-Kermit was designed to be compiled under VAX C 3.1 or newer."
  389.     @ if old_compiler .eqs. "T" then echo tab + -
  390.         "It has not been verified to build properly under this version."
  391.     @ if old_compiler .eqs. "T" then echo tab + -
  392.         "Please exercise caution until you've verified proper operation."
  393.     @ if old_compiler .eqs. "T" then echo ""
  394.     @ del/sym old_compiler
  395.  
  396. ckvcvt.obj : ckvcvt.c
  397.  
  398. wermit_first :
  399.     @ echo "Building WERMIT", -
  400.         share_text, ", ", net_name, " network support", -
  401.         ", VAX/VMS ", _osversion
  402.  
  403. ckvcvt_first :
  404.     @ echo "Building CKVCVT", share_text, ", VAX/VMS ", _osversion
  405.  
  406. ckvker_last :
  407.     @ if f$search(wershare_file) .nes. "" then -
  408.         del 'wershare_file';*
  409.  
  410. wermit_last :
  411.     @ echo "WERMIT compilation complete"
  412.  
  413. ckvcvt_last :
  414.     @ echo "CKVCVT compilation complete"
  415.  
  416. all_last :
  417.     @ echo "WERMIT and CKVCVT compilation complete"
  418.  
  419. cleanup :
  420.     @ if f$search("wart.exe") .nes. "" then del wart.exe;*
  421.     @ if f$search("*.obj") .nes. "" then del *.obj;*
  422.     @ if f$search("ckcpro.c") .nes. "" then del ckcpro.c;*
  423.     @ echo "Cleanup done"
  424.     @ echo ""
  425.  
  426. !! end of ckvker.mms !!
  427.